package leilei.jace.com.tcpdemo2.client;

import android.text.TextUtils;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import leilei.jace.com.tcpdemo2.text.ConstantValue;
import leilei.jace.com.tcpdemo2.util.LogUtil;
import leilei.jace.com.tcpdemo2.util.SmartCarDecoder;
import leilei.jace.com.tcpdemo2.util.SmartCarEncoder;

/**
 * Created by leilei on 2018/4/4.
 */

public class TcpClient {
    private ExecutorService executorService = Executors.newFixedThreadPool(20);
    public static HashMap<String, String> hashMap = new HashMap<>();
    private int count = 0;

    private TcpClient() {
    }

    private static class SingletonHolder {
        private static final TcpClient INSTANCE = new TcpClient();
    }

    public static TcpClient getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public synchronized void StartTcpClient(String ip_all) {
        final String[] array = ip_all.split(",");
        for (int i = 0; i < array.length; i++) {
            final int finalI = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    Iterator iterator = hashMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry entry = (Map.Entry) iterator.next();
                        String key = (String) entry.getKey();
                        String value = (String) entry.getValue();
                        LogUtil.e("键值对", key + "||" + value);
                        if (key.contains(array[finalI]) && value.equals("true")) {
                            array[finalI] = "";
                        }
                    }
                    if (!TextUtils.isEmpty(array[finalI])) {
                        LogUtil.e("连接的IP地址", array[finalI] + "==");
                        TcpClient.getInstance().connect(array[finalI]);
                    }
                }
            });
        }
    }

    public ChannelFuture connect(String hostname) {
        EventLoopGroup group = new NioEventLoopGroup();
        ChannelFuture channelFuture = null;
        try {
            Bootstrap b = new Bootstrap();//创建Bootstrap
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .remoteAddress(new InetSocketAddress(hostname, ConstantValue.TCP_PORT))
                    .handler(new ChannelInitializer<io.netty.channel.socket.SocketChannel>() {
                        @Override
                        protected void initChannel(io.netty.channel.socket.SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS));
                            ch.pipeline().addLast(new SmartCarEncoder());
                            ch.pipeline().addLast(new SmartCarDecoder());
                            ch.pipeline().addLast(new ClientHandler());
                        }
                    });
            channelFuture = b.connect().sync();//连接到远程节点,阻塞等待直到连接完成
            if (channelFuture.isSuccess()) {
//                hashMap.put(hostname, "true");
                count = 0;
                LogUtil.e("远程节点连接成功", "远程节点连接成功");
            } else {
                hashMap.put(hostname, "false");
                LogUtil.e("远程节点连接失败", "远程节点连接失败");
            }
            channelFuture.channel().closeFuture().sync();//阻塞，直到Channel关闭
        } catch (InterruptedException e) {
            LogUtil.e("与服务器连接失败", "与服务器连接失败");
            e.printStackTrace();
        } catch (Exception e) {
            LogUtil.e("与服务器连接失败抛出异常", "与服务器连接失败抛出异常");
            if (count < ConstantValue.TCP_CONNECT_COUNT) {
                count++;
                TcpClient.getInstance().connect(hostname);
            }
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();//关闭线程池并且释放所有的资源
        }
        return channelFuture;
    }

    public boolean isConnect(String hostname) {
        Iterator iterator = hashMap.entrySet().iterator();
        boolean isconnect = false;
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            LogUtil.e("键值对", key + "||" + value);
            if (key.contains(hostname) && value.equals("true")) {
                isconnect = true;
            } else {
                isconnect = false;
            }
        }
        return isconnect;
    }
}
